package myJs.user.workflow.featureSelection.cor

import com.softwaremill.quicklens._
import myJs.myPkg.reactHookForm._
import myJs.tool.Tool._
import myJs.user.workflow.featureSelection.FileSelectCp
import shared.Pojo.MetDataKind
import shared.pojo.WorkflowMission._

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import myJs.Implicits._
import myJs.cps._
import myJs.tool.Tool

import japgolly.scalajs.react.vdom.all._
import japgolly.scalajs.react._
import japgolly.scalajs.react.React.Fragment
import japgolly.scalajs.react.util.EffectCatsEffect._
import myJs.myPkg.Hooks._
import cats.effect._
import myJs.Implicits._

/** Created by yz on 3/11/2020
  */
object CorCp {

  case class Props(
      curI: Int,
      data: EachCorData,
      dataChange: EachCorData => SyncIO[Unit],
      extraData: ExtraData,
      extraDataChange: ExtraData => SyncIO[Unit]
  ) {
    @inline def render: VdomElement = {
      Component(this)
    }
  }

  val Component = ScalaFnComponent[Props] { props =>
    val useForm = ReactHookForm.useFormContext()
    val curTool = Cor
    val namePrefix = s"cor.${props.curI}"

    object FTool {

      def extraFileSelect = (v: String) => {
        SyncIO {} >> {
          val newExtraData = props.extraData
            .modify(_.fileSelectShow)
            .setTo(false)
          props.extraDataChange(newExtraData)
        } >> {
          val newData = props.data
            .modify(_.extraFile)
            .setTo(v)
          useForm.setValue(s"${namePrefix}.extraFile", v)
          props.dataChange(newData)
        }
      }.unsafeRunSync()

      def fileSelectShow = {
        val newData = props.extraData
          .modify(_.tabs)
          .setTo(List(MetDataKind.name, "example"))
          .modify(_.fileSelectShow)
          .setTo(true)
          .modify(_.fileSelect)
          .setTo(FTool.extraFileSelect)
          .modify(_.exampleFileName)
          .setTo("extra_data.txt")
        props.extraDataChange(newData)
      }

      def confounderFileSelect = (v: String) =>
        {
          val newExtraData = props.extraData
            .modify(_.fileSelectShow)
            .setTo(false)
          val newData = props.data
            .modify(_.confounderFile)
            .setTo(v)
          useForm.setValue(s"${namePrefix}.confounderFile", v)
          props.dataChange(newData) >>
            props.extraDataChange(newExtraData)
        }.unsafeRunSync()

      def confounderFileSelectShow = {
        val newData = props.extraData
          .modify(_.tabs)
          .setTo(List(MetDataKind.name))
          .modify(_.fileSelectShow)
          .setTo(true)
          .modify(_.fileSelect)
          .setTo(FTool.confounderFileSelect)
        props.extraDataChange(newData)
      }

      def hasConfounderChange = (v: Boolean) => {
        val newData = props.data.modify(_.hasConfounder).setTo(v)
        props.dataChange(newData)
      }

      def corMethodChange = (v: String) => {
        val newData = props.data.modify(_.corMethod).setTo(v)
        props.dataChange(newData)
      }

      def fdrMethodChange = (v: String) => {
        val newData = props.data.modify(_.fdrMethod).setTo(v)
        props.dataChange(newData)
      }

      def coeChange = (v: String) => {
        val newData = props.data.modify(_.coe).setTo(v)
        props.dataChange(newData)
      }

      def pChange = (v: String) => {
        val newData = props.data.modify(_.p).setTo(v)
        props.dataChange(newData)
      }

      def fdrChange = (v: String) => {
        val newData = props.data.modify(_.fdr).setTo(v)
        props.dataChange(newData)
      }

      def nodeSizeChange = (v: String) => {
        val newData = props.data.modify(_.nodeSize).setTo(v)
        props.dataChange(newData)
      }

    }
    val formState = ReactHookForm.useFormState(options =
      UseFormStateOptions(
        name = namePrefix
      )
    )

    useEffect(
      SyncIO {
        Tool.refreshNodeColor(props.data.nodeId, formState, namePrefix)
      },
      List(formState)
    )

    val data = props.data
    val corMethodMap = SeqMap(
      "pearson" -> "Pearson",
      "spearman" -> "Spearman",
      "kendall" -> "Kendall"
    )
    val fdrMethodMap = SeqMap(
      "fdr" -> messages("FDRBH"),
      "bonferroni" -> "Bonferroni",
      "holm" -> "Holm"
    )

    div(
      FileSelectCp
        .Props(
          fileSelectShow = FTool.fileSelectShow,
          label = messages("anotherDataMatrix"),
          name = s"${namePrefix}.extraFile",
          value = data.extraFile,
          questionInfo = messages("anotherDataMatrixInfo"),
          show = true
        )
        .render,
      ToggleCp
        .Props(
          value = data.hasConfounder,
          label = messages("runPCorAnalysis"),
          name = s"${namePrefix}.hasConfounder",
          valueChange = FTool.hasConfounderChange
        )
        .render,
      FileSelectCp
        .Props(
          fileSelectShow = FTool.confounderFileSelectShow,
          label = messages("dataMatrixOfCovariates"),
          name = s"${namePrefix}.confounderFile",
          value = data.confounderFile,
          questionInfo = messages("covariatesInfo"),
          show = data.hasConfounder
        )
        .render,
      SelectCp
        .Props(
          value = data.corMethod,
          label = messages("method"),
          name = s"${namePrefix}.corMethod",
          optionMap = corMethodMap,
          onChange = FTool.corMethodChange
        )
        .render,
      SelectCp
        .Props(
          value = data.fdrMethod,
          label = messages("adjustPBy"),
          name = s"${namePrefix}.fdrMethod",
          optionMap = fdrMethodMap,
          onChange = FTool.fdrMethodChange
        )
        .render,
      InputCp
        .Props(
          value = data.coe,
          show = true,
          label = messages("correlationCutoff"),
          name = s"${namePrefix}.coe",
          onChange = FTool.coeChange,
          questionInfo = messages("corInfo")
        )
        .render,
      InputCp
        .Props(
          value = data.p,
          show = true,
          label = messages("pValueCutoff"),
          name = s"${namePrefix}.p",
          onChange = FTool.pChange,
          questionInfo = messages("pInfo")
        )
        .render,
      InputCp
        .Props(
          value = data.fdr,
          show = true,
          label = messages("adjustedPCutoff"),
          name = s"${namePrefix}.fdr",
          onChange = FTool.fdrChange,
          questionInfo = messages("fdrInfo")
        )
        .render,
      InputCp
        .Props(
          value = data.nodeSize,
          show = true,
          label = messages("ThresholdOfRelatedNodes"),
          name = s"${namePrefix}.nodeSize",
          onChange = FTool.nodeSizeChange,
          questionInfo = messages("ThresholdOfRelatedNodesInfo")
        )
        .render
    )

  }

}
